package com.zjdiepu.www.biz;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

import javax.annotation.Resource;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import com.aliyun.oss.model.Callback;
import com.aliyun.oss.model.Callback.CalbackBodyType;
import com.zjdiepu.www.base.core.ApiResponse;
import com.zjdiepu.www.base.enums.type.ResultFlagType;
import com.zjdiepu.www.biz.ibiz.IFileHelpService;
import com.zjdiepu.www.biz.ibiz.IOSSFileSerivce;
import com.zjdiepu.www.common.consts.ThreadFactory;
import com.zjdiepu.www.common.util.FileUtil;
import com.zjdiepu.www.common.util.StringUtil;
import com.zjdiepu.www.common.util.UUIDFactory;
import com.zjdiepu.www.commpent.OSSCommpent;
import com.zjdiepu.www.config.FileProperty;
import com.zjdiepu.www.config.OSSProperty;
import com.zjdiepu.www.ibiz.base.IOtherAttachmentsService;
import com.zjdiepu.www.model.base.dto.OtherAttachments;
import com.zjdiepu.www.model.base.ext.OtherAttachmentsExt;

/**
 * 项目名称：dpqc-parent-manager-file <br/> 
 * 类名称：FileServiceImpl <br/>  
 * 类描述：文件上传操作实现 <br/>    
 * 创建人：xiongxiaotun <br/> 
 * 创建时间：2017年4月10日 上午11:15:33  <br/>   
 * 修改人：xiongxiaotun <br/> 
 * 修改时间：2017年4月10日 上午11:15:33   <br/>  
 * 修改备注：    <br/> 
 * @version V1.0   <br/>
 */
@Service
public class OSSFileServiceImpl implements IOSSFileSerivce {
	private  Logger logger = LoggerFactory.getLogger(getClass());
	
	@Autowired
	private IOtherAttachmentsService otherAttachmentsService;
	@Autowired
	private IFileHelpService fileHelpService;
	@Resource
	private OSSProperty ossProperty;
	@Resource
	private FileProperty fileProperty;
	@Resource
	private OSSCommpent ossCommpent;
	
	@Override
	public ApiResponse saveToCloud(MultipartFile uploadFile, String currentUserId, String currentUserName, String savePath, String modeId) {
		try {
			long size = uploadFile.getSize();
			if(size == 0) {
				return  ApiResponse.fail(ResultFlagType.FILE_NOT_SELECTED);
			}
			String uuid = UUIDFactory.getUUID();
			//后缀
			String name = uploadFile.getOriginalFilename(); //show name
			String fileSuffix = FileUtil.getFileSuffix(name);
			String tempName = uuid + StringUtil.PERIOD + fileSuffix; // save name
			savePath = savePath + tempName; // save path
			OtherAttachments otherAttachments = new OtherAttachments();
			otherAttachments.initInsertData(currentUserId, currentUserName);
			otherAttachments.setModeId(modeId);
			otherAttachments.setLocalFilePath(savePath);
			otherAttachments.setOssPath(savePath);
			otherAttachments.setFileSize((int)uploadFile.getSize());
			otherAttachments.setFileName(tempName);
			otherAttachments.setFileShowName(name);
			
			Map<String, String> reuslt;
			if(ossProperty.getSynSwitch()) {
				Future<Map<String, String>> submit = ThreadFactory.THREAD_SERVICE.submit(new Callable<Map<String, String>>() {
					@Override
					public Map<String, String> call() throws Exception {
						return uploadFile(uploadFile, otherAttachments);
					}
				});
				reuslt = submit.get();
			} else {
				reuslt = uploadFile(uploadFile, otherAttachments);
			}
			return ApiResponse.success(reuslt);
		} catch (IOException | InterruptedException | ExecutionException e) {
			logger.error("文件上传到云盘失败.", e);
			return ApiResponse.fail(ResultFlagType.FILE_UPLOAD_FAIL);
		}
	}
	
	/**
	 * 上传文件
	 * @throws IOException 
	 */
	private Map<String, String> uploadFile(MultipartFile uploadFile, OtherAttachments otherAttachments) throws IOException{
		//上传前保存一条记录
		InputStream inputStream;
		if(ossProperty.getLocalCopy()) {
			otherAttachments.setFileHandleStatus("01");
			String realPath = fileProperty.getPath() + otherAttachments.getLocalFilePath();
			File file = new File(realPath);
			FileUtils.copyInputStreamToFile(uploadFile.getInputStream(), new File(realPath));
			inputStream = new FileInputStream(file);
		} else {
			inputStream = uploadFile.getInputStream();
		}
		if(ossProperty.getCallbackSwitch()) {
			otherAttachmentsService.insertJust(otherAttachments);
			Callback callback = packageCallback(otherAttachments);
			ossCommpent.upload(inputStream, otherAttachments.getOssPath(), otherAttachments.getFileName(), callback);
		} else {
			ossCommpent.upload(inputStream, otherAttachments.getOssPath(), otherAttachments.getFileName());
			//上传成功后保存数据(只缺失referId)
			otherAttachments.setFileHandleStatus("01");
			otherAttachmentsService.insert(otherAttachments);
		}
		String authorizedUrl = ossCommpent.getUrlAndAuthorized(otherAttachments.getOssPath());
		Map<String, String> result = new HashMap<String, String>();
		result.put("name", uploadFile.getName()); //表单名称
		result.put("fileId", otherAttachments.getId());
		result.put("url", authorizedUrl);
		result.put("uploadName", otherAttachments.getFileName());
		return result;
	}

	/**
	 * 定时任务，查询表数据，然后完成断点续传
	 */
	@Override
	public boolean saveCheckPointToCloud(String modelId ,String dataId, Integer pageSize, Integer startPage) {
		if(StringUtils.isBlank(modelId) || StringUtils.isBlank(dataId)) {
			return false;
		}
		OtherAttachmentsExt otherAttachmentsExt = new OtherAttachmentsExt();
		otherAttachmentsExt.setPage(startPage);
		otherAttachmentsExt.setRows(pageSize);
		otherAttachmentsExt.setModeId(modelId);
		otherAttachmentsExt.setDataid(dataId);
		otherAttachmentsExt.setFileHandleStatus("01"); //已经处理好，待上传
		otherAttachmentsExt.setNotDeleted(true);
		List<OtherAttachments> otherAttachmentss = otherAttachmentsService.selectByExt(otherAttachmentsExt);
		for(OtherAttachments file : otherAttachmentss) {
			OtherAttachments otherAttachments = new OtherAttachments();
			otherAttachments.setId(file.getId());
			otherAttachments.setOssPath(file.getOssPath());
			
			Callback callback = null;
			if(ossProperty.getCallbackSwitch()) {
				callback = packageCallback(file);
			} else {
				otherAttachments.setFileHandleStatus("01");
				otherAttachments.setFileSize(file.getFileSize());
			}
			
			if(!ossCommpent.exist(file.getOssPath())){ //不存在才上传
				ossCommpent.uploadCheckPoint(fileProperty.getPath() + file.getLocalFilePath(), file.getOssPath(), file.getFileShowName(), callback);
			} else {
				otherAttachments.setFileHandleStatus("01"); 
			}
			//上传成功后更改状态
			otherAttachmentsService.update(otherAttachments);
		}
		return true;
	}
	
	/**
	 * 分装callback
	 */
	private Callback packageCallback(OtherAttachments otherAttachments){
		/**
		 * 注释查看
		 * @see OSSCallback
		 */
		Callback ossCallback = new Callback();
		ossCallback.setCallbackHost(ossProperty.getCallbackHost());
		ossCallback.setCallbackUrl(ossProperty.getCallbackUrl());
		ossCallback.setCalbackBodyType(CalbackBodyType.JSON);
		String ossCallbackBodyFormat = "";
		if(FileUtil.isValid(otherAttachments.getFileShowName())) {
			ossCallbackBodyFormat = "{\\\"object\\\":${object},\\\"mimeType\\\":${mimeType},\\\"size\\\":${size},\\\"imageInfo.height\\\":${imageInfo.height}"
					+ ",\\\"imageInfo.width\\\":${imageInfo.width},\\\"imageInfo.format\\\":${imageInfo.format},\\\"data.id\\\":${x:data.id}}";
		} else {
			ossCallbackBodyFormat = "{\\\"object\\\":${object},\\\"mimeType\\\":${mimeType},\\\"size\\\":${size}"
					+ ",\\\"data.id\\\":${x:data.id}}";
		}
		ossCallback.setCallbackBody(ossCallbackBodyFormat);
		ossCallback.addCallbackVar("x:data.id", otherAttachments.getId()); //文件附属的数据
		return ossCallback;
	}
	
}
